using System;
using System.Collections.Generic;
using System.Text;
using System.Windows.Documents;
using System.Windows.Shapes;
using System.Windows;
using System.Windows.Media;

namespace WozLib.UI.Adorners
{
  public class DropPreviewAdorner : Adorner
  {

    // Adding some basic fields to help us keep track of where we are and what we render
    private Rectangle m_Child;
    private double m_LeftOffset;
    private double m_TopOffset;


    //The first to do when subclassing the Adorner class is to add the appropriate constructor.

    public DropPreviewAdorner(UIElement adornedElement, UIElement adorningElement)
      : base(adornedElement)
    {

      //' By default, an adorner will be sized the same
      //' as its target element, and positioned the
      //' same as its target element. Works beautifully for us. :)
      VisualBrush brush = new VisualBrush(adorningElement);

      m_Child = new Rectangle();
      m_Child.Width = adorningElement.RenderSize.Width;
      m_Child.Height = adorningElement.RenderSize.Height;
      m_Child.Fill = brush;
      m_Child.IsHitTestVisible = false;

      //' For extra effect, we'll animate the opacity of the brush.
      //...
    }

    //Now, many adorners will simply render their own content. Because we're lazy and we're using a Rectangle instead, we need to make sure the layout system knows about this and lays it out appropriately (we'll simply size to content).

    //protected override Size MeasureOverride(Size constraint)
    //{
    //  m_Child.Measure(constraint);
    //  return m_Child.DesiredSize;
    //}

    //protected override Size ArrangeOverride(Size finalSize)
    //{
    //  m_Child.Arrange(new Rect(finalSize));
    //  return finalSize;
    //}

    //protected override Visual GetVisualChild(int index)
    //{
    //  return m_Child;
    //}

    //protected override System.Collections.IEnumerator LogicalChildren
    //{
    //  get
    //  {
    //    List<UIElement> list = new List<UIElement>();
    //    list.Add(m_Child);
    //    return list.GetEnumerator();
    //  }
    //}

    //Protected Overrides ReadOnly Property VisualChildrenCount() As Integer
    // Get
    //  Return 1
    // End Get
    //End Property

    //With this bit of code, we can already show the rectangle we wanted.

    //We'll want to allow the drag/drop code we wrote in the window to update the adorner to follow the mouse, so we'll add a couple of properties for this.

    public double LeftOffset
    {
      get
      {
        return m_LeftOffset;
      }
      set
      {
        m_LeftOffset = value;
        UpdatePosition();
      }
    }

    public double TopOffset
    {
      get
      {
        return m_TopOffset;
      }
      set
      {
        m_TopOffset = value;
        UpdatePosition();
      }
    }

    private void UpdatePosition()
    {
      AdornerLayer adornerLayer = this.Parent as AdornerLayer;

      if (adornerLayer != null)
      {
        adornerLayer.Update(AdornedElement);
      }

    }

    //Finally, adorners are always placed relative to the element they adorn. You can then place them relative to the corners, the middle, off to the side, within, etc. We'll just offset the adorner to where the user would like to drop the dragged element, by adding a translate transform to whatever was necessary to get to the adorned element.

    //public override GeneralTransform GetDesiredTransform(GeneralTransform transform)
    //{
    //  GeneralTransformGroup result = new GeneralTransformGroup();
    //  result.Children.Add(base.GetDesiredTransform(transform));
    //  result.Children.Add(new TranslateTransform(LeftOffset, TopOffset));
    //  return result;
    //}

    // A common way to implement an adorner's rendering behavior is to override the OnRender
    // method, which is called by the layout subsystem as part of a rendering pass.
    protected override void OnRender(DrawingContext drawingContext)
    {
      
      // base the rect around the width, height and mouse position
      Rect rect = new Rect(m_LeftOffset, m_TopOffset, m_Child.Width, m_Child.Height);

      // use a semi-transparent visual brush of the selected item
      Brush brush = m_Child.Fill;
      brush.Opacity = 0.6;

      // give it a thing black border
      Pen pen = new Pen(new SolidColorBrush(Colors.Black), 0.7);

      drawingContext.DrawRectangle(brush, pen, rect);

    }

  }
}
